package com.my.test.design.singleinstance;

public class SingleInstance2 {

    // volatile关键字防止指令重排
    private static volatile SingleInstance2 s2;

    private SingleInstance2() {

    }

    // 不能保证多线程环境下单例
    public static SingleInstance2 getInstance1() {
        if (s2 == null) {
            s2 = new SingleInstance2();
        }
        return s2;
    }

    // 方法加锁避免线了程安全问题，锁的粒度比较大效率低
    synchronized public static SingleInstance2 getInstance2() {
        if (s2 == null) {
            s2 = new SingleInstance2();
        }
        return s2;
    }

    // 鉴于以上的2个问题才有双重锁机制
    public static SingleInstance2 getInstnce3() {
        // 需要三个步骤
        // 1、分配内存
        // 2、实例化对象
        // 3、将实例化对象指向内存
        // 其中2和3可能会出现指令重排，导致线程A其实并没有实例化完成，
        // 但是该对象已经指向内存,另一个线程B判断
        // if (singleton == null)为false直接退出，有可能发生空指针
        if (s2 == null){
            synchronized (SingleInstance2.class){
                if (s2 == null){
                    s2 = new SingleInstance2();
                }
            }
        }
        return s2;
    }


}
